package com.ml.constant;

import java.net.ConnectException;
import java.sql.SQLException;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.ml.enums.StatusCode;
import com.ml.exception.ExchangeException;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 
 * @author Virgil
 * @Date 2018年7月22日
 * @Describe
 *           <p>
 *           统一返回值
 *           </p>
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BaseResult<T> {

	/**
	 * 错误码
	 */
	private Integer code;

	/**
	 * 错误提示信息
	 */
	private String msg;

	/**
	 * 返回值
	 */
	private T data;

	public BaseResult(T data) {
		this.data = data;
		this.code = StatusCode.SUCCESS.code;
		this.msg = StatusCode.SUCCESS.msg;
	}

	public BaseResult(int code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	public static BaseResult<?> getDefaultSuccessResult() {
		return BaseResult.builder().code(StatusCode.SUCCESS.code).msg(StatusCode.SUCCESS.msg).build();
	}

	public static BaseResult<?> ok(Object data) {
		return BaseResult.builder().code(StatusCode.SUCCESS.code).msg(StatusCode.SUCCESS.msg).data(data).build();
	}

	public static BaseResult<?> getSuccessResult(String msg) {
		return BaseResult.builder().code(StatusCode.SUCCESS.code).msg(msg).build();
	}

	public static BaseResult<?> getDefaultFailureResult() {
		return BaseResult.builder().code(StatusCode.FAILURE.code).msg(StatusCode.FAILURE.msg).build();
	}

	public static BaseResult<?> failure(String msg) {
		return BaseResult.builder().code(StatusCode.FAILURE.code).msg(msg).build();
	}

	public static BaseResult<?> getDefaultResult(Integer code, String msg) {
		return BaseResult.builder().code(code).msg(msg).build();
	}

	/**
	 * <p>
	 * 返回成功,有数据
	 * </p>
	 * 
	 * @param message 操作说明
	 * @param data    对象
	 * @return JsonResult
	 */
	public BaseResult<T> success(String message, T data) {
		this.setCode(StatusCode.SUCCESS.code);
		this.setMsg(message);
		this.setData(data);
		return this;
	}

	/**
	 * <p>
	 * 返回成功,有数据
	 * </p>
	 * 
	 * @param data 对象
	 * @return JsonResult
	 */
	public BaseResult<T> success(T data) {
		this.setCode(StatusCode.SUCCESS.code);
		this.setMsg("success");
		this.setData(data);
		return this;
	}

	/**
	 * <p>
	 * 返回成功,无数据
	 * </p>
	 * 
	 * @param message 操作说明
	 * @return JsonResult
	 */
	public BaseResult<T> success(String message) {
		this.setCode(StatusCode.SUCCESS.code);
		this.setMsg(message);
		this.setData(null);
		return this;

	}

	/**
	 * <p>
	 * 返回失败,无数据
	 * </p>
	 * 
	 * @param message 消息
	 * @return JsonResult
	 */
	public BaseResult<T> error(String message) {
		this.setCode(StatusCode.FAILURE.code);
		this.setMsg(message);
		this.setData(null);
		return this;
	}

	/**
	 * <p>
	 * 返回失败,有数据
	 * </p>
	 * 
	 * @param message 消息
	 * @param data    对象
	 * @return JsonResult
	 */
	public BaseResult<T> error(String message, T data) {
		this.setCode(StatusCode.FAILURE.code);
		this.setMsg(message);
		this.setData(data);
		return this;
	}

	public BaseResult(StatusCode error) {
		this.code = error.code;
		this.msg = error.msg;
	}

	public BaseResult(Throwable throwable) {
		this.code = StatusCode.FAILURE.code;
		if (throwable instanceof ExchangeException) {
			this.code = ((ExchangeException) throwable).getCode();
			this.msg = throwable.getMessage();
		} else if (throwable instanceof NullPointerException) {
			this.code = 1001;
			this.msg = "空指针：" + throwable;
		} else if (throwable instanceof ClassCastException) {
			this.code = 1002;
			this.msg = "类型强制转换异常：" + throwable;
		} else if (throwable instanceof ConnectException) {
			this.code = 1003;
			this.msg = "链接失败：" + throwable;
		} else if (throwable instanceof IllegalArgumentException) {
			this.code = 1004;
			this.msg = "传递非法参数异常：" + throwable;
		} else if (throwable instanceof NumberFormatException) {
			this.code = 1005;
			this.msg = "数字格式异常：" + throwable;
		} else if (throwable instanceof IndexOutOfBoundsException) {
			this.code = 1006;
			this.msg = "下标越界异常：" + throwable;
		} else if (throwable instanceof SecurityException) {
			this.code = 1007;
			this.msg = "安全异常：" + throwable;
		} else if (throwable instanceof SQLException) {
			this.code = 1008;
			this.msg = "数据库异常：" + throwable;
		} else if (throwable instanceof ArithmeticException) {
			this.code = 1009;
			this.msg = "算术运算异常：" + throwable;
		} else if (throwable instanceof RuntimeException) {
			this.code = 1010;
			this.msg = "运行时异常：" + throwable;
		} else if (throwable instanceof Exception) {
			this.code = 9999;
			this.msg = "未知异常" + throwable;
		}
	}
}
